base: add single precision versions of all gray reference code
authorØyvind Kolås <pippin@gimp.org>
Wed, 29 Aug 2018 15:35:33 +0000 (17:35 +0200)
committerØyvind Kolås <pippin@gimp.org>
Wed, 29 Aug 2018 15:35:33 +0000 (17:35 +0200)
babl/base/model-gray.c

index 33df8dcc11bd2eb2c5ef5b955c64e9799c43a405..a5cbe318d3393a0f6e475143c67666ca65da521c 100644 (file)
@@ -28,6 +28,7 @@ static void components (void);
 static void models (void);
 static void conversions (void);
 static void formats (void);
+static void init_single_precision (void);
 
 void babl_base_model_gray (void)
 {
@@ -35,6 +36,7 @@ void babl_base_model_gray (void)
   models ();
   conversions ();
   formats ();
+  init_single_precision ();
 }
 
 static void
@@ -893,3 +895,712 @@ formats (void)
     babl_component_from_id (BABL_GRAY_NONLINEAR),
     NULL);
 }
+
+/********** float versions ***********/
+
+static void
+rgba_to_graya_float (Babl *conversion,
+                     char *src,
+                     char *dst,
+                     long  n)
+{
+  const Babl *space = babl_conversion_get_source_space (conversion);
+  float RGB_LUMINANCE_RED   = space->space.RGBtoXYZf[3];
+  float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+  float RGB_LUMINANCE_BLUE  = space->space.RGBtoXYZf[5];
+
+  while (n--)
+    {
+      float red, green, blue;
+      float luminance, alpha;
+
+      red   = ((float *) src)[0];
+      green = ((float *) src)[1];
+      blue  = ((float *) src)[2];
+      alpha = ((float *) src)[3];
+
+      luminance = red * RGB_LUMINANCE_RED +
+                  green * RGB_LUMINANCE_GREEN +
+                  blue * RGB_LUMINANCE_BLUE;
+
+      ((float *) dst)[0] = luminance;
+      ((float *) dst)[1] = alpha;
+
+      src += sizeof (float) * 4;
+      dst += sizeof (float) * 2;
+    }
+}
+
+static void
+rgba_to_gray_float (Babl *conversion,
+                    char *src,
+                    char *dst,
+                    long  n)
+{
+  const Babl *space = babl_conversion_get_source_space (conversion);
+  float RGB_LUMINANCE_RED   = space->space.RGBtoXYZf[3];
+  float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+  float RGB_LUMINANCE_BLUE  = space->space.RGBtoXYZf[5];
+
+  while (n--)
+    {
+      float red, green, blue;
+      float luminance;
+
+      red   = ((float *) src)[0];
+      green = ((float *) src)[1];
+      blue  = ((float *) src)[2];
+
+      luminance = red * RGB_LUMINANCE_RED +
+                  green * RGB_LUMINANCE_GREEN +
+                  blue * RGB_LUMINANCE_BLUE;
+
+      ((float *) dst)[0] = luminance;
+
+      src += sizeof (float) * 4;
+      dst += sizeof (float) * 1;
+    }
+}
+
+static void
+rgb_to_gray_nonlinear_float (Babl  *conversion,
+                             int    src_bands,
+                             char **src,
+                             int   *src_pitch,
+                             int    dst_bands,
+                             char **dst,
+                             int   *dst_pitch,
+                             long   n)
+{
+  const Babl *space = babl_conversion_get_destination_space (conversion);
+  const Babl *trc = space->space.trc[0];
+  float RGB_LUMINANCE_RED   = space->space.RGBtoXYZf[3];
+  float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+  float RGB_LUMINANCE_BLUE  = space->space.RGBtoXYZf[5];
+
+  BABL_PLANAR_SANITY
+  while (n--)
+    {
+      float red, green, blue;
+      float luminance, alpha;
+
+      red   = *(float *) src[0];
+      green = *(float *) src[1];
+      blue  = *(float *) src[2];
+      if (src_bands > 3)
+        alpha = *(float *) src[3];
+      else
+        alpha = 1.0;
+
+      luminance = red   * RGB_LUMINANCE_RED +
+                  green * RGB_LUMINANCE_GREEN +
+                  blue  * RGB_LUMINANCE_BLUE;
+      *(float *) dst[0] = babl_trc_from_linear (trc, luminance);
+
+      if (dst_bands == 2)
+        *(float *) dst[1] = alpha;
+
+      BABL_PLANAR_STEP
+    }
+}
+
+
+static void
+gray_nonlinear_to_rgb_float (Babl *conversion,
+                             int    src_bands,
+                             char **src,
+                             int   *src_pitch,
+                             int    dst_bands,
+                             char **dst,
+                             int   *dst_pitch,
+                             long   n)
+{
+  const Babl *space = babl_conversion_get_source_space (conversion);
+  const Babl *trc = space->space.trc[0];
+
+  BABL_PLANAR_SANITY
+  while (n--)
+    {
+      float luminance;
+      float red, green, blue;
+      float alpha;
+
+      luminance = babl_trc_to_linear (trc, *(float *) src[0]);
+      red       = luminance;
+      green     = luminance;
+      blue      = luminance;
+      if (src_bands > 1)
+        alpha = *(float *) src[1];
+      else
+        alpha = 1.0;
+
+      *(float *) dst[0] = red;
+      *(float *) dst[1] = green;
+      *(float *) dst[2] = blue;
+
+      if (dst_bands > 3)
+        *(float *) dst[3] = alpha;
+
+      BABL_PLANAR_STEP
+    }
+}
+
+static void
+rgb_to_gray_perceptual_float (Babl  *conversion,
+                              int    src_bands,
+                              char **src,
+                              int   *src_pitch,
+                              int    dst_bands,
+                              char **dst,
+                              int   *dst_pitch,
+                              long   n)
+{
+  const Babl *space = babl_conversion_get_destination_space (conversion);
+  const Babl *trc = perceptual_trc;
+  float RGB_LUMINANCE_RED   = space->space.RGBtoXYZf[3];
+  float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+  float RGB_LUMINANCE_BLUE  = space->space.RGBtoXYZf[5];
+
+  BABL_PLANAR_SANITY
+  while (n--)
+    {
+      float red, green, blue;
+      float luminance, alpha;
+
+      red   = *(float *) src[0];
+      green = *(float *) src[1];
+      blue  = *(float *) src[2];
+      if (src_bands > 3)
+        alpha = *(float *) src[3];
+      else
+        alpha = 1.0;
+
+      luminance = red   * RGB_LUMINANCE_RED +
+                  green * RGB_LUMINANCE_GREEN +
+                  blue  * RGB_LUMINANCE_BLUE;
+      *(float *) dst[0] = babl_trc_from_linear (trc, luminance);
+
+      if (dst_bands == 2)
+        *(float *) dst[1] = alpha;
+
+      BABL_PLANAR_STEP
+    }
+}
+
+static void
+gray_perceptual_to_rgb_float (Babl *conversion,
+                              int    src_bands,
+                              char **src,
+                              int   *src_pitch,
+                              int    dst_bands,
+                              char **dst,
+                              int   *dst_pitch,
+                              long   n)
+{
+  const Babl *trc = perceptual_trc;
+
+  BABL_PLANAR_SANITY
+  while (n--)
+    {
+      float luminance;
+      float red, green, blue;
+      float alpha;
+
+      luminance = babl_trc_to_linear (trc, *(float *) src[0]);
+      red       = luminance;
+      green     = luminance;
+      blue      = luminance;
+      if (src_bands > 1)
+        alpha = *(float *) src[1];
+      else
+        alpha = 1.0;
+
+      *(float *) dst[0] = red;
+      *(float *) dst[1] = green;
+      *(float *) dst[2] = blue;
+
+      if (dst_bands > 3)
+        *(float *) dst[3] = alpha;
+
+      BABL_PLANAR_STEP
+    }
+}
+
+
+static void
+graya_to_rgba_float (Babl *conversion,
+                     char *src,
+                     char *dst,
+                     long  n)
+{
+  while (n--)
+    {
+      float luminance;
+      float red, green, blue;
+      float alpha;
+
+      luminance = ((float *) src)[0];
+      alpha     = ((float *) src)[1];
+      red       = luminance;
+      green     = luminance;
+      blue      = luminance;
+
+      ((float *) dst)[0] = red;
+      ((float *) dst)[1] = green;
+      ((float *) dst)[2] = blue;
+      ((float *) dst)[3] = alpha;
+
+      src += sizeof (float) * 2;
+      dst += sizeof (float) * 4;
+    }
+}
+
+
+static void
+gray_to_rgba_float (Babl *conversion,
+                    char *src,
+                    char *dst,
+                    long  n)
+{
+  while (n--)
+    {
+      float luminance;
+      float red, green, blue;
+
+      luminance = ((float *) src)[0];
+      red       = luminance;
+      green     = luminance;
+      blue      = luminance;
+
+      ((float *) dst)[0] = red;
+      ((float *) dst)[1] = green;
+      ((float *) dst)[2] = blue;
+      ((float *) dst)[3] = 1.0;
+
+      src += sizeof (float) * 1;
+      dst += sizeof (float) * 4;
+    }
+}
+
+static void
+gray_alpha_premultiplied_to_rgba_float (Babl   *conversion,
+                                        int    src_bands,
+                                        char **src,
+                                        int   *src_pitch,
+                                        int    dst_bands,
+                                        char **dst,
+                                        int   *dst_pitch,
+                                        long   n)
+{
+  BABL_PLANAR_SANITY
+  assert (src_bands == 2);
+  assert (dst_bands == 4);
+
+  while (n--)
+    {
+      float luminance = *(float *) src[0];
+      float alpha;
+      alpha = *(float *) src[1];
+      if (alpha == 0)
+        luminance = 0;
+      else
+      {
+        luminance = luminance / alpha;
+        if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+          alpha = 0.0;
+      }
+
+      *(float *) dst[0] = luminance;
+      *(float *) dst[1] = luminance;
+      *(float *) dst[2] = luminance;
+      *(float *) dst[3] = alpha;
+      BABL_PLANAR_STEP
+    }
+}
+
+
+static void
+rgba_to_gray_alpha_premultiplied_float (Babl   *conversion,
+                                        int    src_bands,
+                                        char **src,
+                                        int   *src_pitch,
+                                        int    dst_bands,
+                                        char **dst,
+                                        int   *dst_pitch,
+                                        long   n)
+{
+  const Babl *space = babl_conversion_get_source_space (conversion);
+  float RGB_LUMINANCE_RED   = space->space.RGBtoXYZf[3];
+  float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+  float RGB_LUMINANCE_BLUE  = space->space.RGBtoXYZf[5];
+
+  BABL_PLANAR_SANITY;
+  assert (src_bands == 4);
+  assert (dst_bands == 2);
+
+  while (n--)
+    {
+      float red   = *(float *) src[0];
+      float green = *(float *) src[1];
+      float blue  = *(float *) src[2];
+      float luminance;
+      float alpha = *(float *) src[3];
+      if (alpha <= BABL_ALPHA_FLOOR)
+      {
+        if (alpha >= 0.0f)
+          alpha = BABL_ALPHA_FLOOR;
+         else if (alpha >= -BABL_ALPHA_FLOOR)
+           alpha = -BABL_ALPHA_FLOOR;
+        if (red == 0.0 && green == 0.0 && blue == 0.0)
+           alpha = 0.0;
+      }
+
+      luminance = red * RGB_LUMINANCE_RED +
+                  green * RGB_LUMINANCE_GREEN +
+                  blue * RGB_LUMINANCE_BLUE;
+
+      luminance *= alpha;
+
+      *(float *) dst[0] = luminance;
+      *(float *) dst[1] = alpha;
+      BABL_PLANAR_STEP
+    }
+}
+
+static void
+non_premultiplied_to_premultiplied_float (Babl  *conversion,
+                                          int    src_bands,
+                                          char **src,
+                                          int   *src_pitch,
+                                          int    dst_bands,
+                                          char **dst,
+                                          int   *dst_pitch,
+                                          long   n)
+{
+  BABL_PLANAR_SANITY
+
+  while (n--)
+    {
+      int    band;
+      float alpha = *(float *) src[src_bands-1];
+      if (alpha < BABL_ALPHA_FLOOR)
+      {
+        int non_zero_components = 0;
+        if (alpha >= 0.0f)
+          alpha = BABL_ALPHA_FLOOR;
+        else if (alpha >= -BABL_ALPHA_FLOOR)
+          alpha = -BABL_ALPHA_FLOOR;
+
+        for (band = 0; band < src_bands - 1; band++)
+        {
+          if (*(float *) src[band] != 0.0)
+            non_zero_components++;
+        }
+        if (non_zero_components)
+          alpha = 0.0;
+
+      }
+
+      for (band = 0; band < src_bands - 1; band++)
+        {
+          *(float *) dst[band] = *(float *) src[band] * alpha;
+        }
+      *(float *) dst[dst_bands - 1] = alpha;
+
+      BABL_PLANAR_STEP
+    }
+}
+
+static void
+premultiplied_to_non_premultiplied_float (Babl  *conversion,
+                                          int    src_bands,
+                                          char **src,
+                                          int   *src_pitch,
+                                          int    dst_bands,
+                                          char **dst,
+                                          int   *dst_pitch,
+                                          long   n)
+{
+  BABL_PLANAR_SANITY
+
+  while (n--)
+    {
+      int    band;
+      float alpha;
+      alpha = *(float *) src[src_bands-1];
+
+      for (band = 0; band < src_bands - 1; band++)
+        {
+          if (alpha == 0.0)
+            *(float *) dst[band] = 0;
+          else
+            *(float *) dst[band] = *(float *) src[band] / alpha;
+        }
+      if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+        alpha = 0.0;
+      *(float *) dst[dst_bands - 1] = alpha;
+
+      BABL_PLANAR_STEP
+    }
+}
+
+static void
+rgba2gray_nonlinear_premultiplied_float (Babl *conversion,
+                                         char *src,
+                                         char *dst,
+                                         long  n)
+{
+  const Babl *space = babl_conversion_get_destination_space (conversion);
+  const Babl *trc = space->space.trc[0];
+  float RGB_LUMINANCE_RED   = space->space.RGBtoXYZf[3];
+  float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+  float RGB_LUMINANCE_BLUE  = space->space.RGBtoXYZf[5];
+
+  while (n--)
+    {
+      float red   = ((float *) src)[0];
+      float green = ((float *) src)[1];
+      float blue  = ((float *) src)[2];
+      float luminance;
+      float luma;
+      float alpha = ((float *) src)[3];
+      if (alpha < BABL_ALPHA_FLOOR)
+      {
+        if (alpha >= 0.0f)
+          alpha = BABL_ALPHA_FLOOR;
+        else if (alpha >= -BABL_ALPHA_FLOOR)
+          alpha = -BABL_ALPHA_FLOOR;
+        if (red == 0.0 && green == 0.0 && blue == 0.0)
+          alpha = 0.0;
+      }
+
+      luminance = red * RGB_LUMINANCE_RED +
+                  green * RGB_LUMINANCE_GREEN +
+                  blue * RGB_LUMINANCE_BLUE;
+      luma = babl_trc_from_linear (trc, luminance);
+
+      ((float *) dst)[0] = luma * alpha;
+      ((float *) dst)[1] = alpha;
+
+      src += 4 * sizeof (float);
+      dst += 2 * sizeof (float);
+    }
+}
+
+static void
+gray_nonlinear_premultiplied2rgba_float (Babl *conversion,
+                                         char *src,
+                                         char *dst,
+                                         long  n)
+{
+  const Babl *space = babl_conversion_get_destination_space (conversion);
+  const Babl *trc = space->space.trc[0];
+
+  while (n--)
+    {
+      float luma  = ((float *) src)[0];
+      float luminance;
+      float alpha;
+      alpha = ((float *) src)[1];
+      if (alpha == 0.0)
+        luma = 0.0;
+      else
+        luma = luma / alpha;
+
+      luminance = babl_trc_to_linear (trc, luma);
+
+      if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+        alpha = 0.0;
+
+      ((float *) dst)[0] = luminance;
+      ((float *) dst)[1] = luminance;
+      ((float *) dst)[2] = luminance;
+      ((float *) dst)[3] = alpha;
+
+      src += 2 * sizeof (float);
+      dst += 4 * sizeof (float);
+    }
+}
+
+static void init_single_precision (void)
+{
+  babl_format_new (
+    babl_model ("Y"),
+    babl_type_from_id (BABL_FLOAT),
+    babl_component ("Y"),
+    NULL);
+  babl_format_new (
+    babl_model ("Y'"),
+    babl_type_from_id (BABL_FLOAT),
+    babl_component ("Y'"),
+    NULL);
+  babl_format_new (
+    babl_model ("Y~"),
+    babl_type_from_id (BABL_FLOAT),
+    babl_component ("Y~"),
+    NULL);
+
+
+  babl_format_new (
+    babl_model ("YA"),
+    babl_type_from_id (BABL_FLOAT),
+    babl_component ("Y"),
+    babl_component ("A"),
+    NULL);
+  babl_format_new (
+    babl_model ("Y'A"),
+    babl_type_from_id (BABL_FLOAT),
+    babl_component ("Y'"),
+    babl_component ("A"),
+    NULL);
+  babl_format_new (
+    babl_model ("Y~A"),
+    babl_type_from_id (BABL_FLOAT),
+    babl_component ("Y~"),
+    babl_component ("A"),
+    NULL);
+
+
+  babl_format_new (
+    babl_model ("YaA"),
+    babl_type_from_id (BABL_FLOAT),
+    babl_component ("Ya"),
+    babl_component ("A"),
+    NULL);
+  babl_format_new (
+    babl_model ("Y'aA"),
+    babl_type_from_id (BABL_FLOAT),
+    babl_component ("Y'a"),
+    babl_component ("A"),
+    NULL);
+
+  babl_conversion_new (
+    babl_format ("Y' float"),
+    babl_format ("RGBA float"),
+    "planar", gray_nonlinear_to_rgb_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("RGBA float"),
+    babl_format ("Y' float"),
+    "planar", rgb_to_gray_nonlinear_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("Y'A float"),
+    babl_format ("RGBA float"),
+    "planar", gray_nonlinear_to_rgb_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("RGBA float"),
+    babl_format ("Y'A float"),
+    "planar", rgb_to_gray_nonlinear_float,
+    NULL
+  );
+
+
+  babl_conversion_new (
+    babl_format ("Y'aA float"),
+    babl_format ("RGBA float"),
+    "linear", gray_nonlinear_premultiplied2rgba_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("RGBA float"),
+    babl_format ("Y'aA float"),
+    "linear", rgba2gray_nonlinear_premultiplied_float,
+    NULL
+  );
+
+
+
+  babl_conversion_new (
+    babl_format ("Y~ float"),
+    babl_format ("RGBA float"),
+    "planar", gray_perceptual_to_rgb_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("RGBA float"),
+    babl_format ("Y~ float"),
+    "planar", rgb_to_gray_perceptual_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("Y~A float"),
+    babl_format ("RGBA float"),
+    "planar", gray_perceptual_to_rgb_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("RGBA float"),
+    babl_format ("Y~A float"),
+    "planar", rgb_to_gray_perceptual_float,
+    NULL
+  );
+
+
+  babl_conversion_new (
+    babl_format ("YA float"),
+    babl_format ("RGBA float"),
+    "linear", gray_to_rgba_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("YA float"),
+    babl_format ("RGBA float"),
+    "linear", graya_to_rgba_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("RGBA float"),
+    babl_format ("YA float"),
+    "linear", rgba_to_graya_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("RGBA float"),
+    babl_format ("Y float"),
+    "linear", rgba_to_gray_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("YA float"),
+    babl_format ("YaA float"),
+    "planar", non_premultiplied_to_premultiplied_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("YaA float"),
+    babl_format ("YA float"),
+    "planar", premultiplied_to_non_premultiplied_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("YaA float"),
+    babl_format ("RGBA float"),
+    "planar", gray_alpha_premultiplied_to_rgba_float,
+    NULL
+  );
+
+  babl_conversion_new (
+    babl_format ("RGBA float"),
+    babl_format ("YaA float"),
+    "planar", rgba_to_gray_alpha_premultiplied_float,
+    NULL
+  );
+}